package cz.matasek.dbLogger.gui;

import cz.matasek.dbLogger.Constant;
import cz.matasek.dbLogger.exception.DbLoggerRuntimeException;
import java.io.CharArrayReader;
import java.io.Reader;
import java.sql.ResultSet;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;

/**
 * This class is a <code>TableModel</code> of the logging table query result.
 *
 * @author Luboš Matásek
 */
public class LoggingQueryResult extends ResultSetTableModel {

    /**
     * Serial version UID.
     */
    private static final long serialVersionUID = -295565594606149948L;

    /**
     * Creates a new <code>LoggingQueryResult</code> table model.
     *
     * @param queryResultSet the result set of a query
     */
    public LoggingQueryResult(ResultSet queryResultSet) {
        super(queryResultSet);
    }

    /**
     * Returns XML document containing historical table content.
     *
     * @return XML document containing historical table content
     */
    @Override
    public Document getXML() {
        try {
            Document xml =
                    DocumentBuilderFactory.newInstance().
                    newDocumentBuilder().newDocument();
            xml.setXmlStandalone(true);

            Element query = xml.createElementNS(
                    Constant.DB_LOGGER_NAMESPACE, "query");
            query.setAttribute(
                    "xmlns:xsi", Constant.XML_SCHEMA_NAMESPACE);

            for (Object[] rowData : data) {
                Element table = xml.createElement("table");
                table.setTextContent(rowData[1].toString());
                Element user = xml.createElement("user");
                user.setTextContent(rowData[2].toString());
                Element operation = xml.createElement("operation");
                operation.setTextContent(rowData[3].toString());
                Element changed = xml.createElement("changed");
                changed.setTextContent(rowData[4].toString().replace(" ", "T"));
                Element oldValues = xml.createElement("old_values");
                if (rowData[5] == null) {
                    oldValues.setAttribute("xsi:nil", "true");
                } else {
                    Reader reader = new CharArrayReader(rowData[5].toString().toCharArray());
                    Document rowXml =
                            DocumentBuilderFactory.newInstance().
                            newDocumentBuilder().parse(new InputSource(reader));

                    NodeList cols = rowXml.getElementsByTagName("col");

                    for (int i = 0; i < cols.getLength(); ++i) {
                        Element element = xml.createElement("col");
                        element.setAttribute("name", cols.item(i).getAttributes().getNamedItem("name").getTextContent());
                        if (cols.item(i).getAttributes().getNamedItem("xsi:nil") != null) {
                            element.setAttribute("xsi:nil", "true");
                        }
                        element.setTextContent(cols.item(i).getTextContent());
                        oldValues.appendChild(element);
                    }
                }
                Element newValues = xml.createElement("new_values");
                if (rowData[6] == null) {
                    newValues.setAttribute("xsi:nil", "true");
                } else {
                    Reader reader = new CharArrayReader(rowData[6].toString().toCharArray());
                    Document rowXml =
                            DocumentBuilderFactory.newInstance().
                            newDocumentBuilder().parse(new InputSource(reader));

                    NodeList cols = rowXml.getElementsByTagName("col");

                    for (int i = 0; i < cols.getLength(); ++i) {
                        Element element = xml.createElement("col");
                        element.setAttribute("name", cols.item(i).getAttributes().getNamedItem("name").getTextContent());
                        if (cols.item(i).getAttributes().getNamedItem("xsi:nil") != null) {
                            element.setAttribute("xsi:nil", "true");
                        }
                        element.setTextContent(cols.item(i).getTextContent());
                        newValues.appendChild(element);
                    }
                }

                Element row = xml.createElement("row");
                row.appendChild(table);
                row.appendChild(user);
                row.appendChild(operation);
                row.appendChild(changed);
                row.appendChild(oldValues);
                row.appendChild(newValues);

                query.appendChild(row);
            }

            xml.appendChild(query);

            return xml;
        } catch (Exception ex) {
            throw new DbLoggerRuntimeException(ex.getMessage());
        }
    }
}
